package idv.kentYeh.util;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 將陣列包裝為物件供應器
 * @author Kent
 * @param <T> 陣列類別
 */
public class ArraySupplierWrapper<T> implements Supplier<T> {
    
    private static Logger logger = LoggerFactory.getLogger(ArraySupplierWrapper.class);
    private T[] ts = null;
    private AtomicInteger idx = new AtomicInteger(-1);
    public final int MaxSegment = 100;
    private int defaultSegmemt = MaxSegment;
    
    public ArraySupplierWrapper(T[] ts) {
        assert ts != null && ts.length > 0 : "陣列長度必須大於0";
        this.ts = ts;
    }
    
    public ArraySupplierWrapper(T[] ts,int segmemt) {
        assert ts != null && ts.length > 0 : "陣列長度必須大於0";
        this.ts = ts;
        this.setDefaultSegmemt(segmemt);
    }

    /**
     * 取得分段大小
     * @return 分段大小
     */
    public int getDefaultSegmemt() {
        return defaultSegmemt;
    }

    /**
     * 設定分段大小，若小於1則表示分段取出全部
     * @param defaultSegmemt  分段大小, 等於0或小於0時設為100，最大只可設為100
     */
    public void setDefaultSegmemt(int defaultSegmemt) {
        this.defaultSegmemt = defaultSegmemt < 1 ? MaxSegment : defaultSegmemt > MaxSegment ? MaxSegment : defaultSegmemt;
    }
    
    @Override
    public boolean hasNext() {    
        int index = idx.get();
        return index < ts.length-1;
    }
    
    @Override
    public T next() {              
        int index = idx.addAndGet(1);
        if (index == ts.length) {
            idx.set(ts.length - 1);
            return null;
        } else if (index < ts.length) {
            return ts[index];
        } else {
            return null;
        }
    }
    
    @Override
    public T previous() {
        int index = idx.decrementAndGet();
        return index > -1 ? ts[index] : null;
    }
    
    @Override
    public List<T> request() {
        int size = ts.length - idx.get() - 1;
        size = size > defaultSegmemt ? defaultSegmemt : size;
        return request(size);
    }
    
    @Override
    public List<T> request(int size) {
        List<T> result = new ArrayList<T>(size);
        T nxt = null;
        while (size-- > 0 && (nxt = next()) != null) {
            result.add(nxt);
        }
        return result;
    }
    
    @Override
    public void reset() {
        idx.set(-1);
    }
}
